@cipher GIFT_128

sbox uint4[16] s = {1, 10, 4, 12, 6, 15, 3, 9, 2, 13, 11, 7, 5, 0, 8, 14};

#pbox uint[128] p = {0, 33, 66, 99, 96, 1, 34, 67, 64, 97, 2, 35, 32, 65, 98, 3,
#                    4, 37, 70, 103, 100, 5, 38, 71, 68, 101, 6, 39, 36, 69, 102, 7,
#                    8, 41, 74, 107, 104, 9, 42, 75, 72, 105, 10, 43, 40, 73, 106, 11,
#                    12, 45, 78, 111, 108, 13, 46, 79, 76, 109, 14, 47, 44, 77, 110, 15,
#                    16, 49, 82, 115, 112, 17, 50, 83, 80, 113, 18, 51, 48, 81, 114, 19,
#                    20, 53, 86, 119, 116, 21, 54, 87, 84, 117, 22, 55, 52, 85, 118, 23,
#                    24, 57, 90, 123, 120, 25, 58, 91, 88, 121, 26, 59, 56, 89, 122, 27,
#                    28, 61, 94, 127, 124, 29, 62, 95, 92, 125, 30, 63, 60, 93, 126, 31};

#pbox uint[128] p = {31, 126, 93, 60, 63, 30, 125, 92, 95, 62, 29, 124, 127, 94, 61, 28, 27, 122, 89, 56, 59, 26, 121, 88, 91, 58, 25, 120, 123, 90, 57, 24, 23, 118, 85, 52, 55, 22, 117, 84, 87, 54, 21, 116, 119, 86, 53, 20, 19, 114, 81, 48, 51, 18, 113, 80, 83, 50, 17, 112, 115, 82, 49, 16, 15, 110, 77, 44, 47, 14, 109, 76, 79, 46, 13, 108, 111, 78, 45, 12, 11, 106, 73, 40, 43, 10, 105, 72, 75, 42, 9, 104, 107, 74, 41, 8, 7, 102, 69, 36, 39, 6, 101, 68, 71, 38, 5, 100, 103, 70, 37, 4, 3, 98, 65, 32, 35, 2, 97, 64, 67, 34, 1, 96, 99, 66, 33, 0};
pbox uint[128] p = {99, 66, 33, 0, 67, 34, 1, 96, 35, 2, 97, 64, 3, 98, 65, 32, 103, 70, 37, 4, 71, 38, 5, 100, 39, 6, 101, 68, 7, 102, 69, 36, 107, 74, 41, 8, 75, 42, 9, 104, 43, 10, 105, 72, 11, 106, 73, 40, 111, 78, 45, 12, 79, 46, 13, 108, 47, 14, 109, 76, 15, 110, 77, 44, 115, 82, 49, 16, 83, 50, 17, 112, 51, 18, 113, 80, 19, 114, 81, 48, 119, 86, 53, 20, 87, 54, 21, 116, 55, 22, 117, 84, 23, 118, 85, 52, 123, 90, 57, 24, 91, 58, 25, 120, 59, 26, 121, 88, 27, 122, 89, 56, 127, 94, 61, 28, 95, 62, 29, 124, 63, 30, 125, 92, 31, 126, 93, 60};


uint6[48] constants = {1, 3, 7, 15, 31, 62, 61, 60, 55, 47, 30, 60, 57, 51, 39, 14, 29, 58, 53, 43, 32, 44, 24, 48, 33, 2, 5, 11, 23, 46, 28, 56, 49, 35, 6, 13, 27, 54, 45, 26, 52, 41, 18, 36, 8, 17, 34, 4, 9, 19, 38, 12, 25, 50, 37, 10, 21, 42, 20, 40, 16, 32};

r_fn uint1[128] round_function(uint8 r, uint1[64] key, uint1[128] input) {
    uint1[128] s_out;
	for (i from 0 to 31) {
	    #uint1[4] sbox_in = View(input, i*4, i*4+3);
	    uint1[4] sbox_in = {input[i*4+3], input[i*4+2], input[i*4+1], input[i*4]};
        uint1[4] sbox_out = s<sbox_in>;
        s_out[i * 4] = sbox_out[0];
        s_out[i * 4 + 1] = sbox_out[1];
        s_out[i * 4 + 2] = sbox_out[2];
        s_out[i * 4 + 3] = sbox_out[3];
	}

    uint1[128] p_out = p<s_out>;

	for (i from 0 to 31) {
	    p_out[4 * i + 1] = p_out[4 * i + 1] ^ key[i];
	    p_out[4 * i] = p_out[4 * i] ^ key[i + 16];
	}

    #p_out[127] = p_out[127] ^ 1;
	#p_out[23] = p_out[23] ^ constants[r][5];
    #p_out[19] = p_out[19] ^ constants[r][4];
    #p_out[15] = p_out[15] ^ constants[r][3];
    #p_out[11] = p_out[11] ^ constants[r][2];
    #p_out[7] = p_out[7] ^ constants[r][1];
    #p_out[3] = p_out[3] ^ constants[r][0];
	return p_out;
}

fn uint1[128] enc(uint1[2560] key, uint1[128] r_plaintext){
    for (i from 1 to 40) {
        r_plaintext = round_function(i, View(key, (i - 1) * 64, i * 64 - 1), r_plaintext);
    }
    return r_plaintext;
}